package com.laoxiang.modules.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.laoxiang.execption.LxAdminException;
import com.laoxiang.modules.system.entity.SysMenu;
import com.laoxiang.modules.system.entity.dto.RoleMenuTreeSelectDTO;
import com.laoxiang.modules.system.entity.vo.MenuTreeVo;
import com.laoxiang.modules.system.mapper.SysMenuMapper;
import com.laoxiang.modules.system.service.SysMenuService;
import com.laoxiang.utils.AppHttpCodeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 菜单权限表(SysMenu)表服务实现类
 *
 * @author db
 * @since 2023-07-26 08:59:16
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {
    @Autowired
    private SysMenuMapper sysMenuMapper;

    @Override
    public List<MenuTreeVo> treeSelect() {
        List<SysMenu> sysMenus = sysMenuMapper.selectList(null);
        List<MenuTreeVo> menuTreeVoList = buildMenuSelectTree(sysMenus);
        return menuTreeVoList;
    }


    @Override
    public RoleMenuTreeSelectDTO roleMenuTreeSelect(Long roleId) {
        List<SysMenu> sysMenus = sysMenuMapper.selectList(null);
        List<Long> checkedKeys = sysMenuMapper.selectMenuListByRoleId(roleId);
        List<MenuTreeVo> menuTreeVoList = buildMenuSelectTree(sysMenus);
        RoleMenuTreeSelectDTO roleMenuTreeSelectDTO = new RoleMenuTreeSelectDTO(checkedKeys,menuTreeVoList);
        return roleMenuTreeSelectDTO;
    }

    @Override
    public List<SysMenu> getTreeMenuList(SysMenu sysMenu) {
        // menuName模糊查询
        LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.hasText(sysMenu.getMenuName()),SysMenu::getMenuName,sysMenu.getMenuName());
        queryWrapper.eq(Objects.nonNull(sysMenu.getStatus()),SysMenu::getStatus,sysMenu.getStatus());
        //排序 parent_id和order_num
        queryWrapper.orderByAsc(SysMenu::getParentId,SysMenu::getOrderNum);
        List<SysMenu> sysMenus = sysMenuMapper.selectList(queryWrapper);
//        sysMenus = buildMenuTree(sysMenus);
        return sysMenus;
    }

    @Override
    public int addMenu(SysMenu sysMenu) {

        if(Objects.nonNull(sysMenu)){
            // 检查菜单名称是否已存在
            boolean flag = checkMenuNameUnique(sysMenu);
            if(!flag){
                throw new LxAdminException(AppHttpCodeEnum.MENU_EXIST);
            }
            int num = sysMenuMapper.insert(sysMenu);
            return num;
        }

        return 0;
    }

    private boolean checkMenuNameUnique(SysMenu sysMenu) {
        LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysMenu::getMenuName,sysMenu.getMenuName());
        queryWrapper.eq(SysMenu::getParentId,sysMenu.getParentId());
        List<SysMenu> sysMenuList = sysMenuMapper.selectList(queryWrapper);
        if(!CollectionUtils.isEmpty(sysMenuList) && sysMenuList.get(0).getId().longValue() != sysMenu.getId().longValue()){
            return false;
        }

        return true;
    }

    @Override
    public SysMenu getMenuById(Long menuId) {
        SysMenu sysMenu = sysMenuMapper.selectById(menuId);
        return sysMenu;
    }

    @Override
    public void updateMenu(SysMenu sysMenu) {
        // 检查菜单名称是否已存在
        boolean flag = checkMenuNameUnique(sysMenu);
        if(!flag){
            throw new LxAdminException(AppHttpCodeEnum.MENU_EXIST);
        }
        // 修改菜单,失败，上级菜单不能选择自己
        if(sysMenu.getId().equals(sysMenu.getParentId())){
            throw new LxAdminException(AppHttpCodeEnum.MENU_UPDATE_ERROR);
        }
        sysMenuMapper.updateById(sysMenu);
    }

    @Override
    public void deleteMenuById(Long menuId) {

        // 删除之前先判断此菜单是否有子菜单，如果有，不能删除
        LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysMenu::getParentId,menuId);
        Integer integer = sysMenuMapper.selectCount(queryWrapper);
        if(integer>0){
            throw new LxAdminException(AppHttpCodeEnum.MENU_DELETE_ERROR);
        }
        sysMenuMapper.deleteById(menuId);

    }

    private List<SysMenu> buildMenuTree(List<SysMenu> sysMenus) {
        List<SysMenu> menuList= sysMenus.stream()
                .filter(o -> o.getParentId().equals(0L))
                .map(o -> o.setChildren(getChildren(sysMenus, o)))
                .collect(Collectors.toList());
        return menuList;
    }

    private List<SysMenu> getChildren(List<SysMenu> menuList,SysMenu option){
        List<SysMenu> menuTreeList = menuList.stream()
                .filter(o -> Objects.equals(o.getParentId(), option.getId()))
                .map(o -> o.setChildren(getChildren(menuList, o)))
                .collect(Collectors.toList());

        return menuTreeList;
    }

    private List<MenuTreeVo> buildMenuSelectTree(List<SysMenu> menus) {
        List<MenuTreeVo> MenuTreeVos = menus.stream()
                .map(m -> new MenuTreeVo(m.getId(), m.getMenuName(), m.getParentId(), null))
                .collect(Collectors.toList());
        List<MenuTreeVo> menuTreeVoList = MenuTreeVos.stream()
                .filter(o -> o.getParentId().equals(0L))
                .map(o -> o.setChildren(getChildList(MenuTreeVos, o)))
                .collect(Collectors.toList());
        return menuTreeVoList;
    }

    private List<MenuTreeVo> getChildList(List<MenuTreeVo> list, MenuTreeVo option) {
        List<MenuTreeVo> menuTreeVoList = list.stream()
                .filter(o -> Objects.equals(o.getParentId(), option.getId()))
                .map(o -> o.setChildren(getChildList(list, o)))
                .collect(Collectors.toList());
        return menuTreeVoList;
    }
}

